home *** CD-ROM | disk | FTP | other *** search
-
-
-
- WINDOWS SHELL
- FOR MICROSOFT WINDOWS 3.0
- VERSION 2.02
-
-
-
-
- by
-
-
-
-
- Greg McCain
-
- June 5, 1992
-
-
-
-
-
-
-
-
-
-
-
- Advisor: Charles Dana
- Computer Science Department
- School of Engineering
- California Polytechnic State University
- 199
-
-
- TABLE OF CONTENTS
-
- ABSTRACT iii
- LIST OF FIGURES iv
- 0. INTRODUCTION 1
- I. FEATURES OF WINDOWS SHELL 2
- I.A. THE COMMAND LINE 2
- I.B. ALIASES 3
- I.C. ENVIRONMENT VARIABLES 3
- I.D. ACTION BAR 4
- I.E. FILE LIST WINDOW 5
- I.F. EXTERNAL COMMANDS 6
- I.G. SHELL COMMANDS 8
- II. DESIGN OF WINDOWS SHELL 9
- II.A. GRAPHICAL OBJECTS OF THE WINDOWS SHELL 9
- II.A.1 The WSTDIO Window 10
- II.A.1.a Pertinent Data 10
- II.A.1.b Painting The Display 12
- II.A.1.c Obtaining Standard I/O Input 12
- II.A.1.d Marking Text With The Mouse 14
- II.A.1.e Command History 14
- II.A.1.f Wstdio Message Directory 15
- II.A.2 The ACTNBAR Window 16
- II.A.3 The WINSHELL Window 17
- II.B LOGICAL MODULES FOR COMMAND INTERPRETATION 17
- II.B.1 The Command Prompt Path 18
- II.B.2 The Action Button Command Path 19
- II.B.3 The ALIAS.C Module 20
- II.B.4 The INTERP.C Module 21
- III. DEVELOPMENT PROCESS 22
- APPENDIX A. THE EXTERNAL COMMANDS DLL INTERFACE 25
- APPENDIX B. FUTURE ENHANCEMENTS 27
-
-
- ABSTRACT
-
- This document discusses the purpose, features, and design of a command line
- shell for Microsoft Windows 3.0/3.1, the Windows Shell. The Windows Shell allows
- users to launch both DOS and Windows programs from a command line environment,
- as well as perform disk maintenance operations such as copy, deleting, and moving
- files.
- The Windows Shell introduces several new features to the typical command shell
- environment, including interactive editing of Aliases and Environment variables, an
- "Action Bar" to quickly execute a command, the ability to set "permanent" options in
- shell commands, and customizable fonts and screen colors.
- The Windows Shell is designed according to an object oriented paradigm. It is
- comprised of three major graphical objects, which includes the main WINSHELL
- window, the WSTDIO window, and the ACTNBAR window. The task of interpreting and
- executing commands is done by the INTERP (or interpreter) module.
- A key design element of WINSHELL is the WSTDIO window, which provides a
- functional interface much like the normal C standard I/O functions for DOS and UNIX.
- Clients using this window need not implement their own task message loop; the
- WSTDIO window will handle messages transparently when it is invoked. This frees
- the client from having to deal directly with Windows messages, allowing it to focus
- on the task at hand.
-
-
- LIST OF FIGURES
-
- FIGURE
-
- 1-1 The Command Line 2
- 1-2 The Alias Editor 3
- 1-3 The Environment Editor 4
- 1-4 Action Button Configuration 5
- 1-5 File List Window 5
- 1-6 Internal Commands 6
- 2-1 Graphical Object Design 9
- 2-2 Command Interpretation Paths 18
-
-
- 0. INTRODUCTION
- The Windows 3.0 environment provides a graphical user interface for executing programs
- and file management. While this is great for naive users, the graphical interface can be
- cumbersome to experienced users. The Windows Shell is intended for experienced users,
- providing quick manipulation of files and directories, as well as executing Windows and DOS
- programs.
- The Windows Shell was developed on a IBM PS/2 model 70, running at 16 MHz and using a
- VGA display. The shell has also been succesfully run on systems running Windows in SVGA
- and EGA mode.
- This document is divided into three main sections. The first presents the Windows Shell as
- seen by the user. It discusses the feature of Windows Shell, how to access them, and what they
- can do for a user. The second section presents the Windows Shell as seen by the programmer.
- This includes a discussion of the graphical objects seen in the Window Shell, as well as a
- discussion of how the command interpretation works. The last section discusses the
- development process of the Windows Shell. It describes the problems encountered in both
- design and implementation of the Windows Shell, and any other noteworthy considerations that
- were involved in the development process.
- The document also provides the specifications of the DLL External Commands interface in
- Appendix A. The interface is a major consideration when developing external commands for use
- with the Windows Shell.
- I. FEATURES OF WINDOWS SHELL
-
-
- I.A. THE COMMAND LINE
-
- figure 1-1
- The Windows Shell provides a command line interface to the windows environment. The
- command line is similar in appearance to a DOS shell, with the following additions:
- - The Windows Shell prompt allows for text marking, cutting, and pasting.
- - The Windows Shell offers the "Action Bar" seen on the left side of the shell (see figure
- 1-1.)
- - The Windows Shell allows the user to configure the color and font used by each
- instance of the shell.
- - The Windows Shell recognizes the '&' character to run a windows program minimized.
- - The Windows Shell expands partial file names entered on the command line into the
- entire file name by pressing the TAB key. If more than one file matches the partial
- name, the user will be given a choice of files.
-
- I.B. ALIASES
- Windows Shell allows the user to define aliases. Aliases allow long or complex commands
- to be abbreviated for quick access. The Alias Editor (see figure 1-2 below) is provided for quick
- viewing and editing of aliases.
-
-
- figure 1-2
-
- I.C. ENVIRONMENT VARIABLES
-
- Windows Shell provides the Environment Editor (see figure 1-3 below) for quick viewing and
- editing of environment variables. Windows 3.0 provides environment variables similar to that
- of DOS and UNIX. Unfortunately, the environment variables in the Windows Shell are not
- inherited by the programs it executes. Each new task gets a copy of the environment that was
- recorded when windows was started. However, modifying the local environment variables in a
- given application can and will effect the application if it uses them the variables. In the
- Windows Shell, it is sometimes useful to change the path or prompt environment variables.
- Hopefully future versions of Windows will provide inherited environment variables.
-
-
- figure 1-3
-
- I.D. ACTION BAR
- The action bar is a column of eight buttons along the left side of the shell (see figure 1-1) It
- allows users to execute a predefined command at the press of a button. The following window
- is used to configure the action bar:
-
-
- figure 1-4
- The Button Configuration Window allows the users to define the text seen on the buttons and
- the command that is carries out. The user can access text marked on the Windows Shell using
- the '=' character. The '=' character is replaced by a string containing the marked text when the
- command is executed. This makes it easy for a user to mark a block of text and perform actions
- upon it, such as deleting or editing files. For example, to have a button which will delete any
- marked files, use the string:
- del =
- in a "button command" box, as seen in figure 1-4.
-
- I.E. FILE LIST WINDOW
-
-
- figure 1-5
- The File List window lists the files in the current directory. It can be activated using the
- View-File_List menu command, or by pressing Cntrl+F. The File List allows you to select
- multiple files in the current directory, and to either move, copy, or delete the highlighted files. It
- allows you to copy the names of the selected files to the command line. This can be very useful
- when you want to perform a command only on certain files in a directory, but don't know their
- names or you don't want to type them in. Future version of the Windows Shell might include the
- option to sort the files in the File List Window by size, date, or extension.
-
- I.F. EXTERNAL COMMANDS
- Most shells provide shell commands which are built into the shell itself. The Windows Shell
- provides only the most basic shell commands, including: change directory (cd), make directory
- (md), and remove directory (rd). The rest of the usual shell commands are implemented as
- "external commands".
- Each external command is a Windows 3.0 Dynamic Link Library (DLL). The Windows Shell
- uses a Windows 3.0 DLL loading function to load and run external commands. Each external
- command must provide a set of functions to execute the command, show an about box, and
- show an options box.
- The windows shell provides the "external commands window" to view and configure external
- commands (see figure 1-6).
-
-
- figure 1-6
-
- The options box allows the user to set "permanent" options on a command that will be invoked
- each time the command is run. The about box allows the user to view a window which should
- contain useful information on what the command does and how to use it.
- "External commands" are implemented as DLL's to allow new commands to be written without
- modification to the shell. The format of a DLL is such that a normal DOS shell program can
- easily be ported to run under the shell.
-
- I.G. SHELL COMMANDS
- The user accessible commands contained in Winshell, or Shell Commands, are as follows:
- cd <dirname> : Changes current directory to directory specified in dirname.
- md <dirname> : Creates a directory as specified in dirname.
- rd <dirname> : Deletes a directory as specified in dirname.
- <DRIVE> : : Changes current disk specified to drive specified in DRIVE.
- ps : Lists currently running processes.
- min <task_name>: Minimizes program with caption matching task_name.
- max <task_name>: Maximizes program with caption matching task_name.
- kill <task_name>: Closes program with caption matching task_name.
- exit : Exits current Windows Shell.
- exitwin : Exits Windows.
-
-
-
- II. DESIGN OF WINDOWS SHELL
- The design of Windows Shell has been broken down into the many separate modules, both
- graphical and logical. To simplify the explanation of the design, this section is divided into two
- main parts. The first part will discuss the graphical objects of the Windows Shell. This includes
- how the individual windows and buttons are designed, how they function, and they the
- communicate with one another. The second part of this section will discuss the modules used
- in command interpretation. This section will involve a detailed trace of the flow of control for the
- interpretation of a command.
-
- II.A. GRAPHICAL OBJECTS OF THE WINDOWS SHELL
- The windows shell has been divided into three main graphical objects, as seen in figure 2-1.
- Each of the objects is implemented in a separate C source file, and communicate with each
- other via Windows messages. Although the "Main" window as seen in figure 2-1 is at the top of
- the hierarchy, controlling the other two windows, this explanation will be more clear of it starts
- from the bottom.
-
-
- figure 2-1
-
- II.A.1 The WSTDIO Window
- By far the most important window in the shell is the WStdio window. It is responsible for
- supplying the primitives such as reading and writing characters to a standard I/O type device.
- To do this in a windowing environment, is requires creating a "virtual" standard I/O display.
- This display is represented by a data structure, who's main element is an array of characters
- which represent the characters displayed on the screen. When characters are written to the
- WStdio window, they a first copied into this character array, and then are actually displayed on
- the screen.
- II.A.1.a Pertinent Data
- To better understand the implementation of the WStdio window, let's look at the elements of
- the Display data structure as defined by the WStdio window. The first feature is the array of
- characters representing the display (This is referred to as the "LineBuf".) Second, are a set of
- elements used to track the state of the display:
-
- int iTopLine; // Index of the current top line in the LineBuf
- int iBottomLine; // Index of the current bottom line in the
- // LineBuf
- int TotalLineCount; // the current number of line in the LineBuf
- int CurCharOffset; // offset into LineBuff of current position
-
- These first four elements are what control current state of LineBuff itself. LineBuff is an array of
- characters which is logically divided into fixed length lines. The actual number of lines
- available in LineBuff is a constant at compile time, but is typically much larger than the number
- of lines that will currently fit in the window on screen. (This surpluss of lines in memory is used
- as a scrollback buffer, as will be discussed later.) The indices to the top and bottom lines are
- used because LineBuff is a circular buffer. These indices always point to the portion of the
- LineBuff that is currently displayed on the screen. The TotalLineCount variable is the absolute
- number of lines in LineBuff. CurCharOffset is the absolute position in LineBuff at which the next
- character to be displayed will be written.
- The next set of elements is used when actually outputting lines to the screen. Their uses
- and intentions are explained in the comments.
-
- int nLinesOnScreen; // the number of lines fitting on the window
- // in it's current size
- int nCurLineOnScreen; // the current line the cursor is on in window
- // starting from 1 (NOT 0!)
- int yChar, // height in pixels of a line
- int xCaretPos; // distance (in pixels) from the left hand
- // side of the screen that the caret is at
- When the user activates the scrollback feature by using the vertical scrollbar or the PAGE
- UP/PAGE DOWN keys, these variables are initialized and used to track the positioning of the
- scrollback:
-
- BOOL isScrolling; // True is window is in a scrolling back state
- int TopScrollLineNum, // index of the top line in the LineBuff
- // during a scrollback
- Another noteworthy element in the Display data structure is used to expedite the actual
- outputting of lines on the screen.
-
- int nUnpurgedLines, // # of line waiting to be written to
- // the screen
- The WStdio window does not display a line of text immediately when it is received. If
- possible, the window will wait until a predefined constant number of lines come in before it
- actually displays the lines. This can dramatically increase the rate at which lines are displayed
- on the screen. The nUnpurgedLines variable counts the number of lines waiting to be
- displayed. In the current implementation (vers 1.3), this can lead to lines of text not being
- displayed while the task performs some lengthy operation. This should be corrected in later
- versions by having a timer periodically purged any unpurged lines.
- Finally, there are elements used to track how the user has highlighted any text in the WStdio
- window:
-
- WORD wSelectState;
- RECT rectInversion;
- The wSelectState variable can be in three states: one indicating there is no highlighted
- rectangle, when all bits are turned off. The second, SS_SELECTING, indicates the user is
- currently marking a rectangle. The third, SS_RECTSELECTED, indicates that a rectangle is
- currently highlighted. When in third state, the rectInversion variable will hold the coordinates of
- the highlighted rectangle.
- II.A.1.b Painting The Display
- Windows dictates that all screen I/O should be done in response to a WM_PAINT message. This
- message informs a window that it needs to repaint a portion of it's client area, and supplies the
- window with the coordinates of a rectangle it needs to repaint. Thus upon receiving this
- message, the WStdio window calculates what lines need to be painted, and paints them. When
- a client module requests the WStdio window to display a line (via the DM_PUTS message), the
- WStdio window only has to copy the line into it's internal Linebuff, and then invalidate the
- portion of the window that will be effected by the new line. By invalidating a portion of the
- window, Windows will generate a WM_PAINT message, and the proper area of the window will
- be repainted, reflecting the new line to be displayed. This scheme mandates that all screen I/O
- be done in response to the WM_PAINT message, which keeps all screen I/O consistent and in a
- fixed area in the program.
- II.A.1.c Obtaining Standard I/O Input
- Perhaps the most interesting feature in the implementation of the WStdio window is how it
- obtains input from the user. To provide a function like getstr(), which does not return a value
- until the user presses the ENTER key, the Windows message loop had to be placed inside the
- getstr() function. This allows other processes to run and respond to their own inputs while the
- WStdio window is waiting for input.
- When a client module sends a DM_GETS message to get a string from the WStdio window,
- the WStdio window calls it's own DisplayGetStr() function. This function first positions the caret
- at the appropriate position, and then falls into a message loop. Inside this message loop, the
- function monitors the incoming messages looking for the ENTER key to be pressed, in which
- case it will fall out of the loop and return the text that was entered. The function also monitors
- the incoming messages for keys like the arrow keys, in which case it will invoke the command
- history, and for WM_CLOSE message. If a WM_CLOSE message comes in, the DisplayGetStr
- function exits the message loop and returns a value indicating that the function failed.
- With this method of implementing the message loop in the input function, the client modules
- are simplified since they need not implement a separate message loop. The main module of
- the Windows Shell, WINSHELL.C, in fact does not use a message loop. Instead, it falls into a
- loop that might be expected out of a UNIX type command, in which it displays a command
- prompt, gets an input string, interprets it, and executes the appropriate action. It does not use a
- message loop at all, like most other Windows WinMain functions have to do.
- In order to obtain input from the user, the WStdio window uses a Windows edit control.
- When the user sees a prompt at which he or she can type, that prompt is actually inside a
- separate edit control, and not in the WStdio window itself. The edit control is always positioned
- at the end of the last character entered, much as a caret would be. This way, however, leaves
- much of the work of obtaining key-presses and displaying characters to the edit control. It also
- helps provide the standard controls a user might expect from an input prompt, such as marking
- text and replacing text. The user will see an interface consistent with other programs which use
- edit controls. If future versions of Windows change the behavior of these controls, the Windows
- Shell will adapt automatically.
- II.A.1.d Marking Text With The Mouse
- The job of marking text on the display is quite simple. The WStdio window responds to a
- WM_LBUTTONDOWN message (indicating the left mouse button is being pressed,) by obtaining
- a mouse capture. This forces Windows to send all subsequent mouse messages to the window
- obtaining the capture. While in this state, the WStdio window then responds to all
- WM_MOUSEMOVE messages by inverting a rectangle between the position where the mouse
- was originally pressed and the current position. When the left mouse button is released, the
- capture is also released, and the rectangle is left highlighted.
- The portion of highlighted text can now be accessed by both the WStdio window itself, and
- by client windows via the DM_GETMARKEDTEXT message, which is supplied by the wstdio.c
- module. The function GetMarkedText(), in the wstdio.c module, is called in response to this
- message. It is responsible for determining what characters are actually marked and copying
- them to a buffer. This is no simple task when proportionally spaced fonts are in use. The
- function must navigate LineBuff and determine the actual length in pixels of each character in
- the buffer. It then compares this to coordinates that are marked in the screen, and can
- determine what characters are actually marked.
- II.A.1.e Command History
- The WStdio is also responsible for providing a command history. Whenever the user enters
- a command at the command prompt, the WStdio window records the command entered with the
- CommandHistory() function. This function manages a simple queue of a constant size. When a
- user enters a command, it is added at the end of the queue, and the first item in the queue is
- discarded if there are more than the constant limit of items in the queue. When the user
- presses the up and down arrow keys, the WStdio window responds by displaying items from
- this queue on the command line.
- II.A.1.f Wstdio Message Directory
- The following is a list of messages that the WStdio window provides for client modules. The
- messages are defined and processed explicity by the WStdio window. The client can invoke
- these by using the Windows SendMessage() function to send the desired message.
-
- DM_PUTS
- Writes a string to the display.
-
- DM_GETS
- Gets a string from the display.
-
- DM_CLEAR
- Clears the Wstdio window.
-
-
- DM_SETFONT
- Sets the font the Wstdio window will use.
-
- DM_GETNUMCOLUMNS
- Returns the approximate number of columns on the display. A column is space
- enough for about 12 of the widest characters in the current font, and a trailing tab.
- This feature essentially indicates the number of file names that can be displayed
- on one line.
-
- DM_GETMARKEDTEXT
- Returns a global handle to memory block containing marked text. This memory
- must be freed by the user.
-
- DM_SETMORE
- Turns the more feature on and off. When this feature is turned on, the WStdio
- will automatically display a ----more---- at the bottom of the screen after the last
- number of lines displayed has filled up the screen. The more feature is
- automatically turned off when after DM_GETS message is sent.
-
- II.A.2 The ACTNBAR Window
- The actnbar window provides the column of user-configurable push buttons along the left
- hand side of the Windows Shell. Each push button provides a shortcut way for the user to
- execute a command. The ACTNBAR window is actually a rectangular window surrounding the
- set of push buttons. Associated with each push button is a caption and a command. The
- caption is the text that is displayed in the button on the screen; the command is the command
- string which will be invoked when the button is pressed.
- When the ACTNBAR window is created, it creates it's push button children and initializes
- them to defaults saved in the WINSHELL.INI configuration file. It's job thereafter is to report to
- it's parent window whenever one of it's buttons has been pushed, passing the parent window
- the command string to be executed.
- This is accomplished using the standard Windows WM_COMMAND message. This
- message is sent to the ACTNBAR window whenever one of it's children push buttons is pressed.
- The ACTNBAR processes this message by first setting it's own caption (the string of text
- appearing in the caption bar of a window, which is not visible in the ACTNBAR window) to the
- command string of the child being pressed. The ACTNBAR window then relays the same
- WM_COMMAND message to the parent (or client) window. When the parent receives the
- WM_COMMAND from the ACTNBAR window, it reads caption text of the ACTNBAR window, and
- executes the command string contained therein.
- Note that this logical command path is different from that of the other command interpretation
- path. A command executed in response to the ACTNBAR being pressed is interpreted and
- executed in response to the WM_COMMAND message, and is not obtained via the command
- interpretation loop in the WinMain function. This is discussed more in section II.B.2.
- Also contained inside the ACTNBAR.C module is action button configuration dialog box. This
- allows users to configure both the caption and command of each action button.
-
- II.A.3 The WINSHELL Window
- This window is the main window of the application, and controls the other windows as seen
- in figure 2-1. The graphical duties of this window are quite simple. The WINSHELL window
- creates and manages two children windows, the WSTDIO window and the ACTNBAR window.
- Both children are sized so that together they fill up the client area of the WINSHELL window.
- Thus the WINSHELL window reacts to changes in it's own size by repositioning and re-sizing
- the children so they always fill it's client area.
- WINSHELL also provides the menu bar as seen at the top of the window. It must respond to
- menu messages and execute the appropriate functions. These functions include changing the
- font in the WSTDIO window, changing the colors of the Windows Shell, and popping up the
- various configuration dialog boxes. These duties mostly involve sending a single message to
- the appropriate window to perform the task. In this way, the WINSHELL window serves more as
- a message router for it's children than anything else.
- If this seems too simple, it's because the graphically oriented tasks are only part of the
- tasks the WINSHELL window must perform. It's main task, that of command interpretation, is
- discussed in the next section.
- II.B LOGICAL MODULES FOR COMMAND INTERPRETATION
- This section discusses the modules involved in command interpretation. Now that the
- relationship of the 3 main windows has been defined, the matter of understanding command
- interpretation will be much easier. First let's look at the design of the command interpreter, as
- seen in figure 2-2.
-
-
- figure 2-2
-
- The flow of control in figure 2-2 moves left to right. The diamond shaped modules indicate
- modules which are returning user input. The circular modules perform some logical operation
- on the input data, and the square boxes will be the end result of the command.
- There exist two paths in which a command can be executed by the shell. The first is by the
- user entering a command at the command prompt. This is accomplished by looping for user
- input, interpreting it, and executing it. The second path is invoked via the user pressing an
- Action Button; the command is executed immediately in response to the ACTNBAR's message.
- II.B.1 The Command Prompt Path
- Command interpretation begins in the WINSHELL.C module. This module contains the
- WinMain function, which is the entry point of a Windows application. After performing it's
- initializations and creating it's child windows, the WINSHELL.C module falls into the command
- interpretation loop as follows:
- do
- {
- DisplayPrompt (hwndDisplay);
-
- // exit if display says to
- if (dgets (hwndDisplay, szCmdLine, MAX_COMMAND_LENGTH)== -1)
- break;
-
- ExpandAliasString (szCmdLine, MAX_COMMAND_LENGTH);
-
- iInterp = InterpretCommand (hwndWinShell, hwndDisplay, szCmdLine);
- } while (bContinue && iInterp != -1);
- The first function in the loop displays the command prompt on the WStdio window. The next
- job is to obtain a line of text from the user, which is accomplished by the dgets() macro. Dgets()
- is a macro supplied by the WStdio module which sends the DM_PUTS message to a WStdio
- window. Note that if dgets() returns -1, it means the user has closed the window, and the loop
- must be exited. After the user input has been obtained, the input is passed to the
- ExpandAliasString() function defined in the ALIAS.C module, which will expand any aliases found
- in the string. Finally, the string is passed to the InterpretCommand function in the INTERP.C
- module. It is in this module that the string is parsed and executed.
- Note that commands retrieved from the command line are not given a chance to expand the
- marked text symbol by using the WSTDIO.C module. The marked text symbol is provided so
- that the symbol in the command string is replaced by the text marked in the WStdio window.
- Although this would be a desirable feature, a minor design flaw stopped me from implementing it
- (see section 3).
- II.B.2 The Action Button Command Path
- The ACTNBAR.C module can instigate a command by sending a message to the WINSHELL
- window. The WINSHELL responds by executing the command using the flow of control as seen
- in figure 2-2. The following code is executed in response to such a message:
- GetWindowText (LOWORD (lParam), szCmdLine, MAX_COMMAND_LENGTH);
- ExpandAliasString (szCmdLine, MAX_COMMAND_LENGTH);
- ExpandMarkedText (szCmdLine, MAX_COMMAND_LENGTH);
- InterpretCommand (hwndWinShell, NULL, szCmdLine);
- As you can see, the code is very similar to that used in the command interpretation loop in
- the previous section. The only difference is that commands executed in response to the
- ACTNBAR module get to use the ExapandMarkedText() function, which expands the marked text
- symbol into the text currently marked on the WStdio window. Also, the command executed in
- response to the ACTNBAR module are passed a WStdio window handle of NULL, prohibiting
- them from outputing any data to the WStdio window. This is to safeguard the current text in the
- Wstdio window, which might otherwise be overwritten by the command executed by the button.
- II.B.3 The ALIAS.C Module
- The ALIAS.C module provides alias expansion for command strings. It is implemented as a
- Windows DLL, which provides the following advantages. For all instances of the Windows Shell
- running, they all share a common ALIAS module. This means that if an alias changed in one
- shell, it is changed for all shells, keeping all aliases consistent. This methods also expedites
- the loading process of Windows Shell, because the default aliases only have to be read from
- disk once, for the first module.
- The implementation of the ALIAS module is quite simple. It maintains a dynamically
- resizable array of elements. Each element contains an alias name and an alias value. The
- module provides a dialog box for adding and deleting aliases, and the ExpandAliasString()
- function, which takes a string and expands any aliases within it.
-
- II.B.4 The INTERP.C Module
- The third and perhaps most important module used in command interpretation is the
- INTERP.C module. This module is responsible for parsing a command line, determining what
- type of command it is, and executing the command accordingly. There are three types of
- commands among which the module must discriminate.
- The first type of command the INTERP module looks for are shell commands. These are
- commands who's code is kept inside the Window Shell. This is accomplished by a large switch
- statement that checks if the requested command is amongst those known to be external
- commands. If INTERP determines that command is a shell command, it merely calls the
- function associated with the shell command. All shell commands are contained in the
- COMMANDS.C module. These commands are so trivial they will not be discussed.
- The second type of command the INTERP module looks for are external commands. These
- commands are implemented as Windows DLLs. The INTERP function searches the default
- directory for files who's names match the specified command name and ending with the .WS
- extension. If a corresponding external command file is found, the DLL is loaded and control is
- passed to it. The specifications for an external command are outline in appendix A.
- The third type of command the INTERP module looks for are executable files. Windows
- provides the WinExec() function which performs this function. However, the WinExec function
- only searches for executable files with and extension of .EXE. DOS on the other hand, allows a
- different type of executable file to end with the .COM extension. Also, Windows provides a DOS
- shell configuration file which can also be executed, who's extension is .PIF. In order all these
- types of files to be executed, the INTERP module first gives the WinExec function a crack at
- executing it. If this fails, INTERP then searches the PATH for a file who's name matches the
- command name and ends in either a .COM or a .PIF. If either of these are found, an explicit file
- name and path is created and passed to the WinExec function, which will then execute the
- appropriate files.
- If none of the above types of commands are found to match the specified command, an
- "unknown command" message is displayed in the WStdio window.
-
- III. DEVELOPMENT PROCESS
- This section discusses some of the problems and considerations that I ran into while
- designing and implementing the Windows Shell. On a general note, it seems that many of the
- major design issues I originally set out to implement worked quite well. From the onset, I
- intended to create a Windows application that did not have a message loop in WinMain function.
- I wanted the main module worry more about the matters of command interpretation than
- windowing. The message loop was to be hidden in the screen I/O functions, which is how it is
- now implemented. Also, the idea of having external commands implemented as DLLs worked
- out great. I really had no idea if either of these ideas were feasible when I started.
- Problems Encountered
- The remainder of this section will be organized in a problem-solution format. I will first
- present a problem or consideration, and then discuss how it was solved or overlooked.
-
- P - As mentioned in section II.B.1, commands entered at the command line aren't given a
- chance to expand the marked text symbol into text that is actually marked on the WStdio
- window. I had originally intended to provide this feature, but the implementation in the WStdio
- window prevented it. The problem lies in the fact that a command entered by the user is
- executed only after the user finishes typing the command and presses the ENTER key, which
- immediately generates a newline character. When a newline is output to the WStdio window,
- the marked text is automatically un-marked. Thus by the time the command is being interpreted,
- any marked text is no longer valid. The Action Bar does not have this problem because it does
- not generate a newline character when pressed.
- S - The solution for this problem was to disallow marked text expansion on the command line.
- While this is more or less avoiding the problem, I have not found an acceptable way to rectify it.
-
- P - The Microsoft C functions for manipulating ENVIRONMENT variables do not work in a
- Windows program. I don't know why.
- S - The solution was to get a pointer to the environment area, and do all ENVIRONMENT
- manipulation functions by hand. This was a messy job, but the only way I found to get it to
- work.
-
- P - In Windows, the ENVIRONMENT of the parent is not inherited by the programs is spawns.
- This has made the ENVIRONMENT editor almost useless.
- S - There is nothing that can be done for this, except pray for future releases of Windows to
- change this.
-
- P - The speed of I/O to the display was too slow, running on a 16MHz VGA system. For
- example, as lines were output from an LS command, the rate at which lines were displayed was
- annoyingly slow. This is of course do to the graphical nature of displaying and scrolling text.
- S - The solution was to buffer the lines as they came in, and to output them in bursts. This made
- the code considerably more difficult to understand, but the end result was highly desirable. I
- found that by just buffering every other line, screen I/O was greatly increased.
-
- P - Use of "strtok" C library function is dangerous. Because I am lexically analyzing a
- command line to determine what to execute, what flags to set, etc, I intended to use strtok.
- However, the C library version is not compatible with Windows, because it allocates memory in
- an incompatible way. So I decided I would write my own. However, I realized that the way strtok
- is used will not work in a multi tasking environment. Strtok "remembers" the last parameter you
- gave it, which allows you to call it successively to get the next tokens. But with different
- programs using strtok simultaneously, it will get garbled.
- S - I considered two possible solutions for this problem. The first was to redesign my strtok
- function to always require the string to be parsed as a parameter. The calling routine would
- have to supply two buffers, one holding the source string, the second holding a buffer in which
- strtok could do it's work. This however, would be quite cumbersome for the client using strtok.
- The second solution is to carefully organize the use of strtok so that it is used by all modules in
- a linear fashion, instead of allowing any one module use it any time it likes. That means the
- module must know exactly what state the function is in before using strtok. While the former is
- a more foolproof solution I chose to go with the latter, since it seems to work and required the
- least amount of change.
-
-
-
- APPENDIX A. THE EXTERNAL COMMANDS DLL INTERFACE
-
-
- OVERVIEW
- Each "External Command" is a DLL that contains the code for that command. The
- 'GENERIC.C' and associated files in the GENERIC directory provide a template for creating a
- new External Command.
- An important consideration in implementing a new command is where to store your data.
- In order for your DLL to be completely reentrant, no variable can be stored in the data segment.
- That is, one must not declare variables outside of a function, or declare variables inside a
- function. The reason for this is that each invocation of a DLL function uses that same data
- segment. If a DLL function was called reentrantly, static variables would be overwritten. If a
- DLL requires more data than will fit on the stack, on must use dynamic allocation. Future
- version may get rid of this requirement.
-
- REQUIREMENTS
-
- Each DLL must provide the following 3 functions for use by Windows Shell:
-
- int FAR PASCAL ModuleProc (HWND hwndDisplay, int argc, LPSTR argv[]);
- @ ORDINAL 3
- hwndDisplay - Window handle of STDIO Display to use for I/O.
- argc - Number of command line arguments.
- argv - Array of pointers to command line arguments. The first pointer always points to
- the name of the DLL.
- This function is called to let the DLL do the function which it is providing. For example, if this
- were a DLL providing a file deletion function, the DLL would perform the deletion at this time.
-
- int FAR PASCAL ShowOptions (HWND hwndParent);
- @ ORDINAL 4
- hwndDisplay - Window handle of STDIO Display to use for I/O or as parent.
- This function is called to tell the DLL to show it's options box. The DLL should display a window
- which allows the user to set options in the DLL.
-
- int FAR PASCAL ShowAbout (HWND hwndParent);
- @ ORDINAL 5
- hwndDisplay - Window handle of STDIO Display to use for I/O or as parent.
- This function is called to tell the DLL to show it's about box. The DLL should display an about
- window at this time.
-
- NOTE - It is essential that the DLL export these functions at the specified ordinal value in it's
- .DEF file. Otherwise, The Windows Shell will not properly access the DLL.
-
-
- USING THE DISPLAY
- The header file 'wstdio.h' has been provided for outputing lines and other function to the
- display. The most common of these is dputs(), which you can use to output a line to the display.
- See the header file for the description of the rest of the functions.
-
- UTILITY FUNCTIONS
- The 'wslib.dll' provides several useful functions for parsing command lines, and yielding to
- other applications. It is extremely important that you use the YieldToOthers() function your code
- sits in a tight loop for an extended length of time. See the header file 'wslib.h' for a list of useful
- functions.
-
-
- APPENDIX B. FUTURE ENHANCEMENTS
-
- Possible Future Enhancements
- - User loadable alias files, supporting multiple loads of different files
- - Allow more variables to be user configurable, such as the scrollback buffer size.
- - Add a timer to the WStdio module to periodically purge all unpurged lines.
- - Allow marked text to remain marked as the WStdio window is scrolled. This would allow the
- marked text symbol to be expanded into the marked text for commands issued from the
- command line.
- - Spawn a separate task for each Internal Command as it is run. This would allow the DLL's to
- use static data, because each time a DLL is called, it would be from a different task.
- Page: 2
-
- TABLE OF CONTENTS
-
-
- ABSTRACT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii
-
- HOW THIS DOCUMENT IS ORGANIZED . . . . . . . . . .. . . . . iv
-
- LIST OF FIGURES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v
-
- Section
-
- I. Features of Windows Shell . . . . . . . . . . . . . . . . . . . . . . . . 1
-
- Command Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
-
- Aliasing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
-
- Environment Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
-
- Action Bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
-
- External Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
-
- Shell Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
-
- II. Design of Windows Shell . . . . . . . . . . . . . . . . . . . . . . . . . 7
-
- Graphical Objects in the Windows Shell . . . . . . . . . . . . . 7
-
- The WSTDIO Window . . . . . . . . . . . . . . . . . . . . 8
-
- Pertinent Data . . . . . . . . . . . . . . . . . . . . . . 8
-
- Painting The Display . . . . . . . . . . . . . . . . . 10
-
- Obtaining Standard I/O input . . . . . . . . . . 11
-
- Marking Text . . . . . . . . . . . . . . . . . . . . 12
-
- Command History . . . . . . . . . . . . . . . . . . 13
-
- Message Directory . . . . . . . . . . . . . . . . . 13
-
- The ACTNBAR Window . . . . . . . . . . . . . . . . . . 14
-
- The WINSHELL Window . . . . . . . . . . . . . . . . . 15
-
- Logical Modules For Command Interpretation. . . . . . . . 16
-
- The Command Prompt Path . . . . . . . . . . . . . . . . 17
-
- The Action Button Path . . . . . . . . . . . . . . . . . . . 18
-
- The ALIAS.C Module . . . . . . . . . . . . . . . . . . . . 19
-
- The INTERP.C Module . . . . . . . . . . . . . . . . . . . 19
-
- III. The Development Process . . . . . . . . . . . . . . . . . . . . . 21
-
- Appendix
-
- A. Appendix A: External Commands DLL Interface . . . . . . . . . 23
-
-
- iv
-
- 20
-
-
-